#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "my_header.h"
#include "Motor.h"
#include "Servo.h"
#include "oled.h"
#include "RTC_Time.h"
#include <stdio.h>

//                                   0,0  0,1    1,0  1,1    2,0  2,1    3,0  3,1    4,0  4,1    5,0  5,1    6,0  6,1    7,0  7,1
uint8_t instruct_array_one[8][2] = {{'n', 'o'}, {'w', 'o'}, {'w', 'c'}, {'h', 'o'}, {'h', 'c'}, {'b', 'o'}, {'b', 'c'}, {'s', 'o'}};
uint8_t x1;
uint8_t y1;
uint8_t x2;
uint8_t y2;

int fputc(int charater, FILE *filePointer) {
	uint32_t result = ITM_SendChar(charater);
	return charater;
}

void GPIO_ConfigurationForIndicator(void);

void USART1_Init(void) {
	/** COM1 */
	GPIO_InitTypeDef GPIO_InitStructure;
  USART_InitTypeDef USART_InitStructure;

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1,ENABLE);
  /*
  *  USART1_TX -> PA9 , USART1_RX ->	PA10
  */				
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);

  //USART_InitStructure.USART_BaudRate = 115200;
	USART_InitStructure.USART_BaudRate = 9600;
  USART_InitStructure.USART_WordLength = USART_WordLength_8b;
  USART_InitStructure.USART_StopBits = USART_StopBits_1;
  USART_InitStructure.USART_Parity = USART_Parity_No;
  USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
  USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;

  USART_Init(USART1, &USART_InitStructure);
  USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
  USART_ClearFlag(USART1,USART_FLAG_TC);
  USART_Cmd(USART1, ENABLE);
}

void USART3_Init(void) {
	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);

	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_Init(GPIOB, &GPIO_InitStructure);

	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_Init(GPIOB, &GPIO_InitStructure);

	NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);

	USART_InitStructure.USART_BaudRate = 115200;
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;
	USART_InitStructure.USART_StopBits = USART_StopBits_1;
	USART_InitStructure.USART_Parity = USART_Parity_No;
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;

	USART_Init(USART3, &USART_InitStructure);
	USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);
	USART_ClearFlag(USART3, USART_FLAG_TC);
	USART_Cmd(USART3, ENABLE);
}

void Sensor_Init(void) {
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_11;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
}

uint32_t Num;
uint32_t CurrentNum;
uint32_t CurrentNumForMotor;
uint32_t CurrentNumForBackupMotor;

void My_Timer_Init_For_Time1(void) {
	TIM_TimeBaseInitTypeDef TIM_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
	TIM_InitStructure.TIM_Period = 10000 - 1;
	TIM_InitStructure.TIM_Prescaler = 7200 - 1;
	TIM_InitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_InitStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_InitStructure.TIM_RepetitionCounter = 0;
	TIM_TimeBaseInit(TIM1, &TIM_InitStructure);
	
	TIM_ClearITPendingBit(TIM1, TIM_IT_Update);
	TIM_ITConfig(TIM1, TIM_IT_Update | TIM_IT_Trigger, ENABLE);
	TIM_Cmd(TIM1, ENABLE);
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
	NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);
}

void TIM1_UP_IRQHandler(void) {
	if (TIM_GetITStatus(TIM1, TIM_IT_Update) != RESET) {
		Num ++;
		TIM_ClearITPendingBit(TIM1, TIM_IT_Update);
	}
}

u8 USART_RX_BUF[200];
u16 USART_RX_STA;

void USART3_IRQHandler(void) {
	u8 Res;
	if (USART_GetITStatus(USART3, USART_IT_RXNE) != RESET) {
		Res = USART_ReceiveData(USART3);
		if ((USART_RX_STA & 0x8000) == 0) {
			if (USART_RX_STA & 0x4000) {
				if (Res != 0x0A) {
					USART_RX_STA = 0;
				} else {
					USART_RX_STA |= 0x8000;
				}
			} else {	
				if (Res == 0x0D) {
					USART_RX_STA |= 0x4000;
				} else {
					//USART_RX_BUF[USART_RX_STA & 0X3FFF] = Res;
					USART_RX_STA ++;
					if (USART_RX_STA > 199) {
						USART_RX_STA = 0;
					}
				}
			}
		}
		USART_SendData(USART3, Res);
		while(USART_GetFlagStatus(USART3, USART_FLAG_TXE) == RESET);
	}
}

void USART1_IRQHandler(void) {
	u8 Res;
	if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) {
		Res = USART_ReceiveData(USART1);
		if ((USART_RX_STA & 0x8000) == 0) {
			if (USART_RX_STA & 0x4000) {
				if (Res != 0x0A) {
					USART_RX_STA = 0;
				} else {
					USART_RX_STA |= 0x8000;
				}
			} else {	
				if (Res == 0x0D) {
					USART_RX_STA |= 0x4000;
				} else {
					USART_RX_BUF[USART_RX_STA & 0X3FFF] = Res;
					USART_RX_STA ++;
					if (USART_RX_STA > 199) {
						USART_RX_STA = 0;
					}
				}
			}
		}
	}
}

int8_t Speed;
int8_t SpeedForBackupMotor;
float Angle;
int main(void) {
	const char* tips = "PowerMCU Starting...";
	printf("Init Default Speed:%d\r\n", Speed);
	OLED_Init();
	OLED_ColorTurn(0);
  OLED_DisplayTurn(0);
	OLED_Clear();
	//OLED_ShowString(0, 0, "ABC", 8, 1);
	//OLED_ShowString(0, 8, "ABC", 12, 1);
	//OLED_ShowString(0, 20, "ABC", 16, 1);
	u8 string[4] = {"ABC\0"};
	OLED_ShowString(0, 36, string, 24, 1);
	OLED_ShowNum(103, 48, 888, 3, 16, 1);
	OLED_Refresh();
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	GPIO_InitTypeDef GPIO_InitStructureForPA0;
	GPIO_InitStructureForPA0.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStructureForPA0.GPIO_Pin = GPIO_Pin_11;
	GPIO_InitStructureForPA0.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructureForPA0);
	
	//------------------------------------
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStructureForBuzzer;
	GPIO_InitStructureForBuzzer.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStructureForBuzzer.GPIO_Pin = GPIO_Pin_12;
	GPIO_InitStructureForBuzzer.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructureForBuzzer);
	GPIO_SetBits(GPIOB, GPIO_Pin_12);
	//------------------------------------
	
	GPIO_ConfigurationForIndicator();

	USART1_Init();
	uint32_t ReceiveData[500];
	//RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
	//DMA_InitTypeDef DMA_InitStruct;
	//DMA_InitStruct.DMA_PeripheralBaseAddr = USART1->DR;
	//DMA_InitStruct.DMA_MemoryBaseAddr = ReceiveData[0];
	//DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralSRC;
	//DMA_InitStruct.DMA_BufferSize = 8;
	//DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
	//DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;
	//DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
	//DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
	//DMA_InitStruct.DMA_Mode = DMA_Mode_Normal;
	//DMA_InitStruct.DMA_Priority = DMA_Priority_Medium;
	//DMA_InitStruct.DMA_M2M = DMA_M2M_Disable;
	//DMA_Init(DMA1_Channel2, &DMA_InitStruct);
	//USART_DMACmd(USART1, USART_DMAReq_Rx, ENABLE);
	//DMA_Cmd(DMA1_Channel2, ENABLE);
	Motor_Init();
	Motor_Init_for_PA3_PA6();
	Servo_Init();
	
	Sensor_Init();
	My_Timer_Init_For_Time1();
	RTC_Init();
	u16 t;
	u16 len;
	uint8_t is_buzzer;
	printf("Init Completed\r\n");
	while (1) {
		struct tm time;
		time = Time_Display();
		if (USART_RX_BUF[21] != 0x0 && USART_RX_BUF[22] != 0x0 && USART_RX_BUF[23] != 0x0 && USART_RX_BUF[24] != 0x0 && USART_RX_BUF[31] != 0x0 && USART_RX_BUF[32] != 0x0) {
			u8 No4OfYear = USART_RX_BUF[21] - 0x30;
			u8 No3OfYear = USART_RX_BUF[22] - 0x30;
			u8 No2OfYear = USART_RX_BUF[23] - 0x30;
			u8 No1OfYear = USART_RX_BUF[24] - 0x30;
			uint16_t year = (No4OfYear * 1000) + (No3OfYear * 100) + (No2OfYear * 10) + No1OfYear;
			u8 No2OfMonth = USART_RX_BUF[25] - 0x30;
			u8 No1OfMonth = USART_RX_BUF[26] - 0x30;
			uint8_t month = (No2OfMonth * 10) + No1OfMonth;
			u8 No2OfDay = USART_RX_BUF[27] - 0x30;
			u8 No1OfDay = USART_RX_BUF[28] - 0x30;
			uint8_t day = (No2OfDay * 10) + No1OfDay;
			u8 No2OfHour = USART_RX_BUF[29] - 0x30;
			u8 No1OfHour = USART_RX_BUF[30] - 0x30;
			uint8_t hour = (No2OfHour * 10) + No1OfHour;
			u8 No2OfMinute = USART_RX_BUF[31] - 0x30;
			u8 No1OfMinute = USART_RX_BUF[32] - 0x30;
			uint8_t minute = (No2OfMinute * 10) + No1OfMinute;
			Alarm_Regulate(year, month, day, hour, minute);
			u8 SetCompleted[5];
			SetCompleted[0] = USART_RX_BUF[29];
			SetCompleted[1] = USART_RX_BUF[30];
			SetCompleted[2] = USART_RX_BUF[31];
			SetCompleted[3] = USART_RX_BUF[32];
			SetCompleted[4] = '\0';
			OLED_ShowString(0, 36, SetCompleted, 24, 1);
			OLED_Refresh();
			USART_RX_BUF[21] = 0x0;
			USART_RX_BUF[22] = 0x0;
			USART_RX_BUF[23] = 0x0;
			USART_RX_BUF[24] = 0x0;
			USART_RX_BUF[25] = 0x0;
			USART_RX_BUF[26] = 0x0;
			USART_RX_BUF[27] = 0x0;
			USART_RX_BUF[28] = 0x0;
			USART_RX_BUF[29] = 0x0;
			USART_RX_BUF[30] = 0x0;
			USART_RX_BUF[31] = 0x0;
			USART_RX_BUF[32] = 0x0;
		}
		u16 is_have_water;
		/** 上拉输入默认是高电平，外接低电平有影响，故只能用来检测外接低电平 */
		if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0) {
			is_have_water = 1;
		} else {
			is_have_water = 0;
		}
		OLED_ShowString(0,0, &USART_RX_BUF[0],8,1);
		//OLED_ShowString(0,8, &USART_RX_BUF[19],12,1);
		OLED_ShowChar(0, 8, USART_RX_BUF[4], 8, 1);
		OLED_ShowNum(0, 20, USART_RX_BUF[4], 2, 16, 1);
		OLED_Refresh();
		if (USART_RX_STA & 0x8000) {
			len = USART_RX_STA & 0x3FFF;
			for (t = 0; t < len; t ++) {
			}
			USART_RX_STA = 0;
		}
		//-------------------------------------------------------------
		//舵机控制
		if (instruct_array_one[x1][y1] == 's' && instruct_array_one[x2][y2] == 'o') {
			u8 hundred_ascii = USART_RX_BUF[17] - 0x30;
			u8 decade_ascii = USART_RX_BUF[18] - 0x30;
			u8 units_ascii = USART_RX_BUF[19] - 0x30;
			uint16_t angleFromBluetooth = (hundred_ascii * 100) + (decade_ascii * 10) + units_ascii;
			if (USART_RX_BUF[16] == 0) {
				Angle = angleFromBluetooth;
			} else {
				Angle = -angleFromBluetooth;
			}
			Servo_SetAngle(Angle);
			Delay_ms(1000);
			x1 = 3;
			y1 = 0;
			x2 = 3;
			y2 = 1;
		}
		uint16_t heat_duration;
		//--------------------------------------------------------------------------------------
		//电饭锅开关控制
		if (instruct_array_one[x1][y1] == 'h' && instruct_array_one[x2][y2] == 'o' && is_have_water == 0) {
			u8 thousand_ascii = USART_RX_BUF[9] - 0x30;
			u8 hundred_ascii = USART_RX_BUF[10] - 0x30;
			u8 decade_ascii = USART_RX_BUF[11] - 0x30;
			u8 units_ascii = USART_RX_BUF[12] - 0x30;
			heat_duration = (thousand_ascii * 1000) + (hundred_ascii * 100) + (decade_ascii * 10) + units_ascii;
			is_buzzer = 1;
			CurrentNum = Num;
			x1 = 4;
			y1 = 0;
			x2 = 4;
			y2 = 1;
			GPIO_SetBits(GPIOA, GPIO_Pin_11);
		}
		//------------------------------------------------------------------------
		//关闭电饭锅并使蜂鸣器响起
		//2024-01-28 18:17:32 (original) ->if (Num - CurrentNum >= 180 * ascii_to_integer && USART_RX_BUF[25] == 0x34) {
		if (Num - CurrentNum >= heat_duration && instruct_array_one[x1][y1] == 'h' && instruct_array_one[x2][y2] == 'c') {
			GPIO_ResetBits(GPIOA, GPIO_Pin_11);
			x1 = 5;
			y1 = 0;
			x2 = 5;
			y2 = 1;
			CurrentNum = 0;
			if (is_buzzer == 1) {
				Delay_ms(500);
				GPIO_ResetBits(GPIOB, GPIO_Pin_12);
				Delay_ms(100);
				GPIO_SetBits(GPIOB, GPIO_Pin_12);
				Delay_ms(100);
				GPIO_ResetBits(GPIOB, GPIO_Pin_12);
				Delay_ms(100);
				GPIO_SetBits(GPIOB, GPIO_Pin_12);
				Delay_ms(700);
				GPIO_ResetBits(GPIOB, GPIO_Pin_12);
				Delay_ms(100);
				GPIO_SetBits(GPIOB, GPIO_Pin_12);
				Delay_ms(100);
				GPIO_ResetBits(GPIOB, GPIO_Pin_12);
				Delay_ms(100);
				GPIO_SetBits(GPIOB, GPIO_Pin_12);
				Delay_ms(700);
				is_buzzer = 0;
			}
		}
		//--------------------------------------------------------------------------------------
		uint16_t water_duration;
		//主抽水马达控制
		if (instruct_array_one[x1][y1] == 'w' && instruct_array_one[x2][y2] == 'o') {
			u8 thousand_ascii = USART_RX_BUF[2] - 0x30;
			u8 hundred_ascii = USART_RX_BUF[3] - 0x30;
			u8 decade_ascii = USART_RX_BUF[4] - 0x30;
			u8 units_ascii = USART_RX_BUF[5] - 0x30;
			water_duration = (thousand_ascii * 1000) + (hundred_ascii * 100) + (decade_ascii * 10) + units_ascii;
			CurrentNumForMotor = Num;
			x1 = 2;
			y1 = 0;
			x2 = 2;
			y2 = 1;
			Speed = 100;
			OLED_ShowNum(103, 48, Speed, 3, 16, 1);
			OLED_Refresh();
			Motor_SetSpeed(Speed);
		}
		int elapsed = Num - CurrentNumForMotor;
		if (elapsed >= water_duration && instruct_array_one[x1][y1] == 'w' && instruct_array_one[x2][y2] == 'c') {
			Speed = 0;
			OLED_ShowNum(103, 48, Speed, 3, 16, 1);
			OLED_Refresh();
			Motor_SetSpeed(Speed);
			CurrentNumForMotor = 0;
			if (USART_RX_BUF[14] == 's') {
				x1 = 7;
				y1 = 0;
				x2 = 7;
				y2 = 1;
			} else {
				x1 = 3;
				y1 = 0;
				x2 = 3;
				y2 = 1;
			}
		}
		//----------------------------------------------------------------------------------------
		//补水马达控制
		if (instruct_array_one[x1][y1] == 'b' && instruct_array_one[x2][y2] == 'o') {
			CurrentNumForBackupMotor = Num;
			x1 = 6;
			y1 = 0;
			x2 = 6;
			y2 = 1;
			SpeedForBackupMotor = 100;
			OLED_ShowNum(103, 48, SpeedForBackupMotor, 3, 16, 1);
			OLED_Refresh();
			Motor_SetSpeed_for_TIM4_PB7_PA3_PA6(SpeedForBackupMotor);
		}
		if (is_have_water == 1 && instruct_array_one[x1][y1] == 'b' && instruct_array_one[x2][y2] == 'c') {
			Delay_ms(1000);
			Delay_ms(1000);
			Delay_ms(1000);
			Delay_ms(1000);
			Delay_ms(1000);
			Delay_ms(1000);
			SpeedForBackupMotor = 0;
			OLED_ShowNum(103, 48, SpeedForBackupMotor, 3, 16, 1);
			OLED_Refresh();
			Motor_SetSpeed_for_TIM4_PB7_PA3_PA6(SpeedForBackupMotor);
			CurrentNumForBackupMotor = 0;
			Angle = -90;
			Servo_SetAngle(Angle);
			Delay_ms(1000);
			x1 = 0;
			y1 = 0;
			x2 = 0;
			y2 = 1;
			uint8_t index = 0;
			uint8_t array_size = sizeof(USART_RX_BUF);
			while (index < array_size) {
				USART_RX_BUF[index] = 0x00;
				index ++;
			}
			OLED_Clear();
			OLED_Refresh();
		}
	}
}

void GPIO_ConfigurationForIndicator(void) {
  GPIO_InitTypeDef GPIO_InitStructure;
  RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOC , ENABLE); 						 	 
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 
  GPIO_Init(GPIOC, &GPIO_InitStructure);
}
